package cn.openea.perpartner.meily.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.HashUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.openea.perpartner.common.core.enums.RabbitEnums;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.text.Convert;
import cn.openea.perpartner.meily.rabbit.domain.BusinessDto;
import cn.openea.perpartner.meily.rabbit.factory.BusinessServiceFactory;
import cn.openea.perpartner.meily.rabbit.service.BusinessService;
import cn.openea.perpartner.meily.thirdparty.UserSystemApi;
import cn.openea.perpartner.meily.web.entity.Customer;
import cn.openea.perpartner.meily.web.entity.Provider;
import cn.openea.perpartner.meily.web.mapper.ProviderMapper;
import cn.openea.perpartner.meily.web.service.ICustomerService;
import cn.openea.perpartner.meily.web.service.IProviderService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (Provider)表服务实现类
 *
 * @author Weird077
 * @since 2023-01-18 19:29:50
 */
@Slf4j
@Service("providerService")
public class ProviderServiceImpl extends ServiceImpl<ProviderMapper, Provider> implements IProviderService, BusinessService {

    private final String defaultUserId = "meily";
    private final String defaultUserName = "玫丽";
    private final String distributorName = "玫丽NO.00000001";
    private final String distributorAddr = "您所在区域未检测出关联区域服务商，欢迎加入我们获最大化收益！";
    private final String distributorImg = "https://www-1308272144.cos.ap-guangzhou.myqcloud.com/Meily/img/PlatformServiceProviderAvatara.jpg";

    private final String distributorId = "00000001";

    @Resource
    private UserSystemApi userSystemApi;
    @Resource
    private ICustomerService customerService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(Provider provider) {

        /**
         * 根据userid判断用户是否已注册区域服务商
         * 2023-04-07 add by lys
         */
        LambdaQueryWrapper<Provider> wrapper = new LambdaQueryWrapper();
        wrapper.eq(Provider::getUserId, provider.getUserId());
        Provider oldProvider = getOne(wrapper);
        if (BeanUtil.isNotEmpty(oldProvider)) {
            provider.setId(oldProvider.getId());
        }

        if (StrUtil.isBlank(provider.getProviderId())) {
            String hash = Convert.toStr(HashUtil.fnvHash(provider.getRealName()));
            String providerId = RandomUtil.randomNumbers(3) + hash.substring(0, 5);
            provider.setProviderId(providerId);
        }
        if (StrUtil.isBlank(provider.getImages())) {
            provider.setImages(provider.getStoreAvatar());
        }
        if (StrUtil.isBlank(provider.getAddress())) {
            String area = provider.getArea();
            String street = provider.getStreet();
            String address = area + "-" + street;
            provider.setAddress(address);
        }
        if(!saveOrUpdate(provider)){
            throw new ServiceException("保存服务商出错了！");
        }

        /**
         * 新增服务商时，同步数据到个人资料
         * 2023-05-08 add by lys
         */
        Customer customer = new Customer();
        customer.setUserId(provider.getUserId());// 用户id
        customer.setUserName(provider.getNickName());// 用户昵称
        customer.setRealName(provider.getRealName());// 真实姓名
        customer.setSex(provider.getSex());// 性别
        customer.setAgeGroup(provider.getAge());// 年龄层
        customer.setPhoneNumber(provider.getPhone());// 手机号码
        customer.setRegion(provider.getArea());// 所在地区
        customer.setStreetVillage(provider.getStreet());// 所在街道
        customer.setProviderId(String.valueOf(provider.getId()));

        Customer oldCustomer = customerService.findByUserId(provider.getUserId());
        if(oldCustomer != null && BeanUtil.isNotEmpty(oldCustomer)){
            customer.setId(oldCustomer.getId());// 唯一id
        }

        if(!customerService.saveOrUpdate(customer)){
            throw new ServiceException("保存数据到个人资料出错了！");
        }

        return true;
    }

    @Override
    public List<Provider> selectList(Provider provider) {
        List<Provider> list = list(buildProviderWrapper(provider, true));
        // 判断是否关注公众号
        Map<String, String> map = userSystemApi.isBindOfficialAccount(list.stream()
                .map(Provider::getUserId)
                .collect(Collectors.toList()));
        if (map == null || map.isEmpty()) {
            return list;
        }
        list.forEach(item -> {
            item.setBindOfficialAccount(StringUtils.isNotBlank(map.get(item.getUserId())) ? map.get(item.getUserId()) : "否");
        });
        return list;
    }

    private LambdaQueryWrapper<Provider> buildProviderWrapper(Provider provider, boolean isSort) {
        if (provider == null) {
            return null;
        }
        LambdaQueryWrapper<Provider> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(provider.getSex())) {
            wrapper.eq(Provider::getSex, provider.getSex());
        }
        if (provider.getIsInitiateGroup() != null){
            wrapper.eq(Provider::getIsInitiateGroup,provider.getIsInitiateGroup());
        }
        if (provider.getIssue() != null){
            wrapper.eq(Provider::getIssue,provider.getIssue());
        }
        if (StrUtil.isNotBlank(provider.getFirstOrderStatus())) {
            wrapper.eq(Provider::getFirstOrderStatus, provider.getFirstOrderStatus());
        }
        if (StrUtil.isNotBlank(provider.getUserId())) {
            wrapper.eq(Provider::getUserId, provider.getUserId());
        }
        if (StrUtil.isNotBlank(provider.getProviderId())) {
            wrapper.eq(Provider::getProviderId, provider.getProviderId());
        }
        if (StrUtil.isNotBlank(provider.getStoreType())){
            wrapper.eq(Provider::getStoreType, provider.getStoreType());
        }
        if (StrUtil.isNotBlank(provider.getPhone())) {
            wrapper.like(Provider::getPhone, provider.getPhone());
        }
        if (StrUtil.isNotBlank(provider.getRealName())){
            wrapper.like(Provider::getRealName, provider.getRealName());
        }
        if (StrUtil.isNotBlank(provider.getStreet())) {
            wrapper.like(Provider::getStreet, provider.getStreet());
        }
        if (StrUtil.isNotBlank(provider.getArea())) {
            wrapper.like(Provider::getArea, provider.getArea());
        }
        if (StrUtil.isNotBlank(provider.getStoreName())) {
            wrapper.like(Provider::getStoreName, provider.getStoreName());
        }
        if (StrUtil.isNotBlank(provider.getStoreTags())) {
            wrapper.like(Provider::getStoreTags, provider.getStoreTags());
        }
        if (StrUtil.isNotBlank(provider.getReferrer())) {
            wrapper.like(Provider::getReferrer, provider.getReferrer());
        }
        String dateRange = provider.getDateRange();
        if (JSONUtil.isJson(dateRange)) {
            JSONObject jsonObject = JSONObject.parseObject(dateRange);
            String startDate = jsonObject.getString("startDate");
            String endDate = jsonObject.getString("endDate");
            if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
                // 比较两个时间的大小
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                if (LocalDate.parse(startDate, formatter).isAfter(LocalDate.parse(endDate, formatter))) {
                    throw new ServiceException("结束时间不能大于开始时间");
                }
                wrapper.apply("DATE(create_time) BETWEEN '" + startDate + "' AND '" + endDate + "'");
            }
        }
        if (isSort) {
            wrapper.orderByDesc(Provider::getUpdateTime);
        }
        return wrapper;
    }

    @Override
    public List<Provider> match(Provider provider) {
        LambdaQueryWrapper<Provider> wrapper = new LambdaQueryWrapper<>();
        String address = provider.getAddress();
        List<Provider> list = new ArrayList<>();
        if (StrUtil.isBlank(address)) {
            Provider provide = new Provider();
            provide.setUserId(defaultUserId);
            provide.setNickName(defaultUserName);
            provide.setProviderId(distributorId);
            provide.setAddress(distributorAddr);
            provide.setImages(distributorImg);
            provide.setStoreName(distributorName);
            list.add(provide);
            return list;
        }
        if (address.lastIndexOf(" ") != -1) {
            address = address.substring(0, address.lastIndexOf(" "));
        }
        wrapper.like(Provider::getAddress, address.trim());
        wrapper.orderByDesc(Provider::getUpdateTime);
        list = list(wrapper);
        if (list.isEmpty()) {
            Provider provide = new Provider();
            provide.setUserId(defaultUserId);
            provide.setNickName(defaultUserName);
            provide.setProviderId(distributorId);
            provide.setAddress(distributorAddr);
            provide.setImages(distributorImg);
            provide.setStoreName(distributorName);
            list.add(provide);
        }
        if (StrUtil.isNotBlank(provider.getUserId())) {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getUserId().equals(provider.getUserId())) {
                    // 如果找到符合条件的元素，先用remove方法将其删除
                    Provider provide = list.remove(i);
                    // 再使用add方法将删除的元素插入到首位
                    list.add(0, provide);
                    break;
                }
            }
        }
        return list;
    }

    @Override
    public Provider getByUserId(String userId) {
        LambdaQueryWrapper<Provider> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Provider::getUserId, userId);
        return getOne(wrapper);
    }

    /**
     * 修改服务商等级
     *
     * @param provider
     * @return
     */
    @Override
    public boolean updateGradeByUserId(Provider provider) {
        LambdaUpdateWrapper<Provider> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Provider::getUserId, provider.getUserId());
        updateWrapper.set(Provider::getGrade, provider.getGrade());
        return update(updateWrapper);
    }

    @Override
    public void editById(@NonNull Provider provider) {
        Optional.ofNullable(baseMapper.selectById(provider.getId()))
                .orElseThrow(() -> new ServiceException("区域服务商不存在"));
        baseMapper.updateById(provider);
    }

    @Override
    public List<Provider> findByIds(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return new ArrayList<>();
        }
        return baseMapper.selectBatchIds(ids);
    }

    @Override
    public TimerTask execute(BusinessDto business) {
        return new TimerTask() {
            @Override
            public void run() {
                //查询所有手机号不为空的用户
                LambdaQueryWrapper<Provider> wrapper = new LambdaQueryWrapper<>();
                wrapper.ne(Provider::getPhone,"");
                wrapper.isNotNull(Provider::getPhone);
                List<Provider> userList = list(wrapper);
                //为防止消息过大，分批发送
                int batchSize = 1000;
                int totalSize = userList.size();
                for (int i = 0; i < totalSize; i += batchSize) {
                    int endIndex = Math.min(i + batchSize, totalSize);
                    List<Provider> subList = userList.subList(i, endIndex);
                    List<JSONObject> sendToList = new ArrayList<>();
                    subList.forEach(user -> {
                        JSONObject sendTo = new JSONObject();
                        sendTo.put("sendTo",user.getRealName());
                        sendTo.put("phoneNumber",user.getPhone());
                        sendToList.add(sendTo);
                    });
                    JSONObject object = business.getParams();
                    object.put("sendParam",sendToList);
                    //将消息发送回回调队列
                    String exchange = RabbitEnums.COMPONET_SMS.getExchange();
                    String routeKey = RabbitEnums.COMPONET_SMS.getRoutingKey();
                    rabbitTemplate.convertAndSend(exchange, routeKey, object, message -> {
                        message.getMessageProperties().setHeader("x-delay", 0);
                        return message;
                    });;
                }
            }
        };
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        BusinessServiceFactory.register("providerService", this);
    }
}

